package com.wpw.java8demo;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONWriter;
import lombok.Builder;
import lombok.Data;
import org.junit.Before;
import org.junit.Test;

public class NumStream {

    List<Apple> appList;

    @Before
    public void before() {
        appList = new ArrayList<>();
        Apple app;
        for (int i = 0; i < 20; i++) {
            app = new Apple();
            app.setColor(String.valueOf(i));
            app.setWeigth(new Random().nextInt(10));
            appList.add(app);
        }
    }

    @Test
    public void test1() {
        IntStream intStream = appList.stream().mapToInt(Apple::getWeigth);
        //int sum = intStream.sum();
        //System.out.println(sum);

        Stream<Integer> boxed = appList.stream().mapToInt(Apple::getWeigth).boxed();
        Integer reduce = boxed.reduce(0, Integer::sum);
        Integer reduce2 = boxed.reduce(0, (a, b) -> a + b);
        System.out.println(reduce);

    }

    @Test
    public void test2() {
        List<Integer> list = new ArrayList<>();
        OptionalInt maxOptinal = list.stream().mapToInt(Integer::intValue).max();
        System.out.println(maxOptinal.orElse(1));

        Integer[] arrays = {1, 6, 6, 6, 6, 6};
        OptionalDouble average = Arrays.stream(arrays).mapToInt(Integer::intValue).skip(1).average();
        System.out.println(average.getAsDouble());
    }

    @Test
    public void test3() {
        IntStream range = IntStream.range(1, 20);
        long count = range.filter(i -> i % 2 == 0).count();
        System.err.println(count);
    }

    @Test
    public void reduceTest() {
        List<ReduceEntity> newList = new ArrayList<>();
        List<ReduceEntity> list = makeList();
        list.stream().collect(Collectors.groupingBy(d -> d.getName())).forEach((name, entiryList) -> {
            entiryList.stream().reduce((a, b) -> {
                return ReduceEntity.builder().name(a.getName()).count(a.getCount() + b.getCount()).build();
            }).ifPresent(newList::add);
        });

        System.out.println(JSON.toJSON(newList, JSONWriter.Feature.PrettyFormat));

        newList.clear();
        Map<String, List<ReduceEntity>> map = list.stream().collect(Collectors.groupingBy(d -> d.getName()));
        map.forEach((name, entiryList) -> {
            entiryList.stream().reduce((a, b) -> {
                return ReduceEntity.builder().name(a.getName()).count(a.getCount() + b.getCount()).build();
            }).ifPresent(newList::add);
        });
        System.out.println(JSON.toJSON(newList, JSONWriter.Feature.PrettyFormat));

    }

    @Test
    public void mapTest() {
        List<ReduceEntity> list = makeList();
        Map<String, ReduceEntity> collect = list.stream().collect(Collectors.toMap(d -> d.getName(), d -> d, (d1, d2) -> {
            return ReduceEntity.builder().name(d1.getName()).count(d1.getCount() + d2.getCount()).build();
        }));
        Collection<ReduceEntity> values = collect.values();
        System.out.println(JSON.toJSON(values, JSONWriter.Feature.PrettyFormat));
    }

    @Data
    @Builder
    public static class ReduceEntity {
        private String name;
        private Integer count;
    }

    public static List<ReduceEntity> makeList() {
        List<ReduceEntity> list = new ArrayList<>();
        list.add(ReduceEntity.builder().name("明").count(1).build());
        list.add(ReduceEntity.builder().name("明").count(2).build());
        list.add(ReduceEntity.builder().name("明").count(3).build());
        list.add(ReduceEntity.builder().name("红").count(6).build());

        return list;
    }
}
